﻿using System;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using LinFu.IoC.Configuration;
using LinFu.IoC.Configuration.Interfaces;
using LinFu.IoC.Interfaces;
using LinFu.IoC;
using LinFu.Reflection;

namespace CoreEx.Services
{
    [LoaderPlugin]
    public class GlobalContainerPlugin : IContainerPlugin
    {
        public void BeginLoad(IServiceContainer target)
        {
            var _serviceContainer = (IServiceContainer)AppDomain.CurrentDomain.GetData("LinFu.Ioc.ServiceContainer");
            if (_serviceContainer == null)
                AppDomain.CurrentDomain.SetData("LinFu.Ioc.ServiceContainer",target);          

            //Make sure that the AssemblyWeavers service is registered in the container.
            if (!target.Contains("AssemblyWeavers", typeof(IDictionary<string, IList<Type>>)))
                target.AddService("AssemblyWeavers", typeof(IDictionary<string, IList<Type>>),
                   new Dictionary<string, IList<Type>>());
        }

        public void EndLoad(IServiceContainer target)
        {
            //Make sure that only one instance of each preprocessor type is present in the container.
            var nativePreProcessors = target.PreProcessors.Where(p => p.GetType().Namespace.Contains("LinFu")).ToList();
                        
            var preProcessors = target.PreProcessors.Where(p => !p.GetType().Namespace.Contains("LinFu")).GroupBy(p => p.GetType()).Select(pg => pg.First()).ToList();                                  
            target.PreProcessors.Clear();
            nativePreProcessors.ForEach(target.PreProcessors.Add);
            preProcessors.ForEach(target.PreProcessors.Add);


            //Make sure that only one instance of each postprocessor type is present in the container.
            var postProcessors = target.PostProcessors.GroupBy(p => p.GetType()).Select(pg => pg.First()).ToList();                                  
            target.PostProcessors.Clear();
            
            //Filter out the initializer so that they can be added at the end of the postprocessor list
            var initializers = postProcessors.Where(p => p.GetType().Name.StartsWith("Initialize")).ToList();
            
            postProcessors.Except(initializers).ToList().ForEach(target.PostProcessors.Add);
            
            initializers.ForEach(target.PostProcessors.Add);
            
            
        }
    }
}